package edu.sjb_beta1.map;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

import javax.swing.ImageIcon;

import org.ini4j.Ini;
import org.ini4j.InvalidFileFormatException;

import edu.sjb_beta1.gui.GUI;

public class Map {
    protected GenericMapElement[][] mapData;
    protected int totalWidth;

    public Map(int w,
            int h) {
        mapData = new GenericMapElement[w][h];
        totalWidth = w;
    }

    public GenericMapElement getElementAt(int w,
            int h) {
        return mapData[w][h];
    }

    public void setElementAt(int w,
            int h,
            GenericMapElement gme) {
        mapData[w][getHeigth() - h - 1] = gme;
    }
    //=====Map loader section=====//
    /*
     * MapLoader uses INI4J library to load data from .sjl files (.ini subformat)
     * INI4J libraries are (C) Ivan Szkiba, 2007-2011 and distributed using
     * Apache License 2.0. 
     */
    public static final int EMPTY = 0x30; // '0'
    public static final int MARIO_START = 0x4D; // 'M'
    public static final int VISIBLE_NONQM = 0x32; // '2'
    public static final int VISIBLE_QM = 0x36; // '6'
    public static final int BOTTOMLESS_PIT = 0x50; // 'P'
    public static final int STAR_GOAL = 0x53; //'S'

    public void loadMapFromIni(Ini iniFile) throws InvalidFileFormatException {
        if (iniFile.keySet().contains("Level")
                && iniFile.keySet().contains("Description")
                && iniFile.keySet().contains("LevelData")) {
            mapData = new GenericMapElement[iniFile.get("Description", "Width",
                    int.class)][iniFile.get("Description", "Heigth", int.class)];
            parseFile(iniFile, this);
        }
        else {
            throw new InvalidFileFormatException("SJL file is invalid or incomplete,"
                    + "some data is missing!");
        }
    }

    public void loadMapFromFile(String filePath)
            throws InvalidFileFormatException,
            IOException,
            IllegalArgumentException {
        Ini iniFile = new Ini(new File(filePath));
        loadMapFromIni(iniFile);
    }

    private void parseFile(Ini f,
            Map m) {
        int i = 0;
        for (String element : f.get("LevelData").keySet()) {
            parseLine(i, f.get("LevelData", element, String.class), m);
            i++;
        }
    }

    private void parseLine(int line,
            String str,
            Map m) {
        for (int column = 0; column < str.length(); column++) {
            switch (new Integer(str.charAt(column))) {
                case EMPTY:
                    m.setElementAt(
                            line,
                            column,
                            new GenericMapElement(
                            new ImageIcon("./images/transparent.png"),
                            new EmptySpace()));
                    break;
                case MARIO_START:
                    GUI.mario.setLocation(
                            column * 32,
                            (getHeigth() - line - 4) * 32);
                    m.setElementAt(
                            line,
                            column,
                            new GenericMapElement(
                            new ImageIcon("./images/transparent.png"),
                            new EmptySpace()));
                    break;
                case VISIBLE_NONQM:
                    m.setElementAt(
                            line,
                            column,
                            new GenericMapElement(
                            new ImageIcon("./images/objects/brick_common.gif"),
                            new MapBrick(false)));
                    break;
                case VISIBLE_QM:
                    m.setElementAt(
                            line,
                            column,
                            new GenericMapElement(
                            new ImageIcon("./images/objects/brick_qm.gif"),
                            new MapBrick(true)));
                    break;
                case BOTTOMLESS_PIT:
                    m.setElementAt(
                            line,
                            column,
                            new GenericMapElement(
                            new ImageIcon("./images/transparent.png"),
                            new BottomlessPit()));
                    break;
                case STAR_GOAL:
                    m.setElementAt(line, column,
                            new GenericMapElement(new ImageIcon(
                            "./images/objects/star.gif"), new GoalPoint()));

                    break;
                default:
                    throw new IllegalArgumentException(
                            "Entered characer doesn't correspond to any existing!");

            }
        }
    }

    public int getWidth() {
        return mapData.length;
    }

    public int getHeigth() {
        return mapData[0].length;
    }
}